001 /*********************************************************************************************** 002 * Tekijä: Jukka Salminen 003 * Opiskelijanumero: i79947 004 * Email: jukka.salminen@uwasa.fi 005 * Tekoaika: 23.9.2002 006 * Kurssi/vuosi: Ohjelmoinnin jatkokurssi/kevät 2002 007 * Työn tunnus: Harjoitustyö: Taulukkoeditori web-sivulle 008 *********************************************************************************************** 009 * JSTableModel-luokka 010 *==================== 011 * JSTableModel-luokka toteuttaa JTableModel-rajapinnan ja suorittaa taulukon datan 012 * hakuun, muuttamiseen ja tallentamiseen tarvittavat toiminnot. 013 * 014 * Metodit 015 *-------- 016 * initComponents Muodostaa taulukon datavektorin 017 * 018 * addEmptyColumn Lisää tyhjän sarakkeen taulukkoon 019 * 020 * addEmptyRow Lisää tyhjän rivin taulukon loppuun 021 * 022 * createEmptyRow Tuottaa sopivan mittaisen vektorin, jossa on 023 * sarakkeita vastaava määrä tyhjiä String-objekteja 024 * 025 * createEmptyColumn Tuottaa uuden sarakeobjektin taulukkoon 026 * 027 * createNewHeader Tuottaa uudelle sarakkeelle otsikon col1, col2 jne. 028 * 029 * getColumnIdentifiers Palauttaa taulukon sarakkeiden otsikot 030 * 031 * removeColumnAndData Poistaa sarakkeen sekä taulukosta 032 * että taulukon datavektorista 033 * 034 * removeRow Poistaa editoitavan rivin taulukosta 035 * 036 * insertRow Lisää tyhjän rivin editoitavan rivin yläpuolelle 037 * 038 * save Tallentaa datan serverille HTTP POST:illa 039 * 040 * getTableData Tuottaa DataHandler-objektin, joka lukee XML-parserin 041 * tuottamaa dataa. Palauttaa Datahandlerin tuottaman 042 * vektorin. Taulukon alkiot ovat datavektorissa. 043 * 044 * toXML Tuottaa taulukon datavektorista XML-merkkijonon 045 * 046 * sortColumnIdentifiers Korjaa sarakkeiden otsikot jo sarakkeita on lisätty 047 * tai niiden paikkoja vaihdettu 048 * Jäsenmuuttujat 049 *--------------- 050 * m_sURL Referenssi URL:ään, josta taulukkodata ladataan 051 * 052 * Paikalliset muuttujat 053 *---------------------- 054 * Dokumentoitu metodien yhteydessä 055 */ 056 057 package tables; 058 import java.util.*; 059 import classes.*; 060 import javax.swing.table.*; 061 import jsxml.*; 062 import java.io.*; 063 import java.net.*; 064 065 public class JSTableModel extends javax.swing.table.DefaultTableModel 066 { 067 String m_sURL; 068 public JSTableModel() 069 { 070 initComponents(); 071 } 072 073 public JSTableModel(String sourceURL) 074 { 075 initComponents(sourceURL); 076 } 077 078 public void initComponents() 079 { 080 // Testidataa Forten IDE:a varten 081 setDataVector(new String [][] 082 { 083 {" ", " ", " ", " "}, 084 {" ", " ", " ", " "}, 085 {" ", " ", " ", " "}, 086 {" ", " ", " ", " "} 087 }, 088 new String [] 089 { 090 "Col1", "Col2", "Col3", "Col4" 091 }); 092 } 093 /*********************************************************************************************** 094 * Metodi initComponents 095 * ===================== 096 * Alustaa taulukon datavektorin 097 * 098 * Parametrit sourceURL URL, josta taulukon data haetaan 099 * 100 * Paikalliset muuttujat 101 *---------------------- 102 * sDataVector Vector, johon data kerätään 103 * maxCellsInRow int, joka sisältää taulukon sarakkeiden lukumäärän 104 ***********************************************************************************************/ 105 public void initComponents(String sourceURL) 106 { 107 try 108 { 109 setURL(sourceURL); 110 // sDataVectoriin haetaan taulukon data 111 // Data on riveittäin, jokainen rivi on yksi vektorin sDataVector rivi 112 Vector sDataVector = getTableData(sourceURL); 113 // Rivit voivat olla erimittaisia ja on selvitettävä suurin rivinpituus 114 // Selvitetään suurin sarakemäärä ja talletetaan maxCellsInRow:n arvoksi 115 int maxCellsInRow=0; 116 for (int i=0; i < sDataVector.size(); i++) 117 { 118 if (((Vector)sDataVector.get(i)).size() > maxCellsInRow) 119 { 120 maxCellsInRow = ((Vector)sDataVector.get(i)).size(); 121 } 122 } 123 // Luodaan sarakkeita varten vektori sColumnVector 124 Vector sColumnVector = new Vector(); 125 for (int i=0; i < maxCellsInRow; i++) 126 { 127 sColumnVector.add("Col"+(i+1)); 128 // sColumnVector.add("Col2"); 129 } 130 // Asetetaan JSTableModelin datavektori 131 setDataVector(sDataVector, sColumnVector); 132 } 133 catch (NullPointerException exc) 134 { 135 initComponents(); 136 return; 137 } 138 } 139 /*********************************************************************************************** 140 * Metodi addEmptyColumn 141 * ===================== 142 * Lisää tyhjän sarakkeen JSTable-taulukkoon ja tähän JSTableModeliin 143 * 144 * Parametrit Ei ole 145 * 146 * Paikalliset muuttujat 147 *---------------------- 148 * newHeader String, jossa teksti "ColN", N = 1,2,3... 149 * newColumn Vektori, jossa String-alkioita sopiva määrä 150 ***********************************************************************************************/ 151 public void addEmptyColumn() 152 { 153 String newHeader = createNewHeader(); 154 Vector newColumn = createEmptyColumn(); 155 addColumn(newHeader, newColumn); 156 } 157 /*********************************************************************************************** 158 * Metodi addEmptyRow 159 * ===================== 160 * Lisää tyhjän rivin JSTable-taulukkoon ja tähän JSTableModeliin 161 * 162 * Parametrit Ei ole 163 * 164 * Paikalliset muuttujat 165 *---------------------- 166 * newRow Vektori, jossa String-alkioita sopiva määrä 167 ***********************************************************************************************/ 168 public void addEmptyRow() 169 { 170 Vector newRow = createEmptyRow(); 171 addRow(newRow); 172 } 173 /*********************************************************************************************** 174 * Metodi createEmptyRow 175 * ===================== 176 * Luo ja palauttaa vektorin newRow, josta tulee uusi rivi tähän JSTableModeliin 177 * 178 * Parametrit Ei ole 179 * 180 * Paikalliset muuttujat 181 *---------------------- 182 * newRow Vektori, jossa String-alkioita sopiva määrä 183 ***********************************************************************************************/ 184 private Vector createEmptyRow() 185 { 186 Vector newRow = new Vector(); 187 for (int i=0; i < getColumnCount(); i++) 188 { 189 newRow.add(i, ""); 190 } 191 return newRow; 192 } 193 /*********************************************************************************************** 194 * Metodi createEmptyColumn 195 * ===================== 196 * Luo ja palauttaa vektorin newColumn, josta tulee uusi sarake JSTableen 197 * 198 * Parametrit Ei ole 199 * 200 * Paikalliset muuttujat 201 *---------------------- 202 * newColumn Vektori, jossa String-alkioita sopiva määrä 203 ***********************************************************************************************/ 204 private Vector createEmptyColumn() 205 { 206 Vector newColumn = new Vector(); 207 for (int i=0; i < getRowCount(); i++) 208 { 209 newColumn.add(i, ""); 210 } 211 return newColumn; 212 } 213 /*********************************************************************************************** 214 * Metodi createNewHeader 215 * ===================== 216 * Luo ja palauttaa sarakeotsikon "ColN", jossa N on aina yhden suurempi kuin 217 * taulukon nykyinen sarakemäärä 218 * 219 * Parametrit Ei ole 220 * 221 * Paikalliset muuttujat 222 *---------------------- 223 * newHeader String, joka sisältää uuden otsikon 224 ***********************************************************************************************/ 225 private String createNewHeader() 226 { 227 String newHeader = "Col"+(getColumnCount()+1); 228 return newHeader; 229 } 230 /*********************************************************************************************** 231 * Metodi getColumnIdentifirers 232 * ============================ 233 * Palauttaa JSTableModelin sarakeotsikot vektorissa 234 ***********************************************************************************************/ 235 public Vector getColumnIdentifiers() 236 { 237 return columnIdentifiers; 238 } 239 /*********************************************************************************************** 240 * Metodi removeColumnAndData 241 * ========================== 242 * Poistaa sarakkeen JSTable-taulukosta ja JSTableModelista. Täytyy poistaa sekä sarake 243 * JSTablen ColumnModelista että fyysinen data JSTableModelin datavektorista 244 * 245 * Parametrit thisTable JSTable-taulukko, joka käyttää tätä modelia 246 * 247 * Paikalliset muuttujat 248 *---------------------- 249 * int colNumber Poistettavan sarakkeen indeksi = editoitavana oleva sarake 250 * TableColumn thisColumn Poistettava sarakeobjekti thisSTable:ssa 251 * int columnModelIndex TableModelissa olevan sarakkeen indeksi, joka vastaa sarakkeessa 252 * thisColumn olevan datan varastoinnista 253 * Vector thisData JSTableModelin datavektori 254 * Enumeration enum Apumuuttuja, joka sisältää TableColumnmodelin sarakkeet 255 * 256 ***********************************************************************************************/ 257 public void removeColumnAndData(JSTable thisTable) 258 { 259 int colNumber = thisTable.getEditingColumn(); 260 if (colNumber == -1) 261 { 262 return; 263 } 264 TableColumn thisColumn = thisTable.getColumnModel().getColumn(colNumber); 265 int columnModelIndex = thisColumn.getModelIndex(); 266 Vector thisData = getDataVector(); 267 Vector columnIdentifiers = getColumnIdentifiers(); 268 269 // Remove the column from the table 270 thisTable.removeColumn(thisColumn); 271 272 // Tässä pitäisi tehdä kokonaan uudet otsikot 273 columnIdentifiers.removeElementAt(columnModelIndex); 274 // Remove the column data 275 for (int r=0; r<thisData.size(); r++) 276 { 277 Vector row = (Vector)thisData.get(r); 278 row.removeElementAt(columnModelIndex); 279 } 280 columnIdentifiers = getColumnIdentifiers(); 281 columnIdentifiers = sortColumnIdentifiers(columnIdentifiers); 282 283 setDataVector(thisData, columnIdentifiers); 284 // Correct the model indices in the TableColumn objects 285 // by decrementing those indices that follow the deleted column 286 Enumeration enum = thisTable.getColumnModel().getColumns(); 287 for (; enum.hasMoreElements(); ) 288 { 289 thisColumn = (TableColumn)enum.nextElement(); 290 if (thisColumn.getModelIndex() >= columnModelIndex) 291 { 292 thisColumn.setModelIndex(thisColumn.getModelIndex()-1); 293 } 294 } 295 fireTableStructureChanged(); 296 } 297 /*********************************************************************************************** 298 * Metodi removeRow 299 * ================= 300 * Poistaa rivin taulukosta ja taulukkomallista 301 * 302 * Parametrit JSTable thisTable 303 * 304 * Paikalliset muuttujat 305 *---------------------- 306 * int rowNumber Poistettavan (editoitavan) rivin numero 307 ***********************************************************************************************/ 308 public void removeRow(JSTable thisTable) 309 { 310 int rowNumber = thisTable.getEditingRow(); 311 if (rowNumber == -1) 312 { 313 return; 314 } 315 // Remove the row from the table model 316 getDataVector().remove(rowNumber); 317 fireTableStructureChanged(); 318 } 319 /*********************************************************************************************** 320 * Metodi insertRow 321 * ================= 322 * Lisää rivin taulukkoon editoitavan rivin yläpuolelle 323 * 324 * Parametrit JSTable thisTable 325 * 326 * Paikalliset muuttujat 327 *---------------------- 328 * int rowNumber Editoitavan rivin numero 329 * Vector newRow Lisättävä vektori 330 ***********************************************************************************************/ 331 public void insertRow(JSTable thisTable) 332 { 333 int rowNumber = thisTable.getEditingRow(); 334 if (rowNumber == -1) 335 { 336 return; 337 } 338 // Insert row above editing row 339 Vector newRow = createEmptyRow(); 340 getDataVector().insertElementAt(newRow, rowNumber); 341 fireTableStructureChanged(); 342 } 343 /*********************************************************************************************** 344 * Metodi save 345 * ================= 346 * Tallettaa taulukon XML-muodossa serverille 347 * Samalla järjestetään taulukko uudelleen, jos sarakkeiden 348 * paikkoja on vaihdettu vetämällä 349 * 350 * Parametrit JSTable thisTable 351 * 352 * Paikalliset muuttujat 353 *---------------------- 354 * Vector vApu Apumuuttuja, jota käytetään taulukkoa järjestettessä 355 * Vector dataVector Taulukkomallin datavektori 356 * Vector newdataVector Taulukkomalliin sijoitettava uusi järjestetty datavektori 357 * Vector newRow Uuteen datavektoriin sijoitettava rivivektori 358 * int iLines Datavektorin pituus, taulukon rivien lukumäärä 359 * Vector columnIdentifiers Taulukon sarakeotsikot 360 * TableColumn thisColumn Taulukon käsiteteltävänä oleva sarake 361 * Enumeration enum Apumuuttuja, joka sisältää TableColumnModelin sarakkeet 362 * int i, r Laskurimuuttujia 363 ***********************************************************************************************/ 364 public void save(JSTable thisTable) 365 { 366 Vector vApu; 367 Vector columnIdentifiers = sortColumnIdentifiers(getColumnIdentifiers()); 368 Vector dataVector = getDataVector(); 369 Vector newDataVector = new Vector(10,10); 370 // Move the column data 371 int iLines = dataVector.size(); 372 for (int r=0; r < iLines; r++) 373 { 374 // Jotta saataisiin kokonaan uusi datavektori täytyy luoda uusia rivejä newRow 375 // Nämä rivit lisätään sitten uuteen datavektoriin newDataVector 376 Vector newRow = new Vector(10,10); 377 vApu = (Vector)dataVector.get(r); 378 // Käydään järjestyksessä läpi kaikki taulukon sarakkeet 379 // Etsitään datavektorista vastaava alkio ja lisätään se uuteen rivivektoriin 380 Enumeration enum = thisTable.getColumnModel().getColumns(); 381 int i = 0; 382 for (; enum.hasMoreElements(); ) 383 { 384 TableColumn thisColumn = (TableColumn)enum.nextElement(); 385 int columnModelIndex = thisColumn.getModelIndex(); 386 // vaihdetaan TableModelissa paikkaa 387 newRow.add(vApu.get(columnModelIndex).toString()); 388 i++; 389 } 390 newDataVector.add(newRow); 391 } 392 // Asetetaan TableModeliin uusi datavektori ja päivitetään näkymää 393 setDataVector(newDataVector, columnIdentifiers); 394 fireTableStructureChanged(); 395 // Jos http-osoite, postataan XML serverille, muuten kirjoitetaan tiedostoon 396 if (m_sURL.startsWith("http")) 397 { 398 post(toXML()); 399 } 400 else 401 { 402 writeToFile(toXML()); 403 } 404 } 405 /*********************************************************************************************** 406 * Metodi sortColumnIdentifiers 407 * ================= 408 * Muodostaa uudet sarakeotsikot, jos sarakkeiden paikkoja on vaihdettu 409 * tai sarakkeita on poistettu 410 * 411 * Parametrit Vector colIDs 412 * 413 * Paikalliset muuttujat 414 *---------------------- 415 * Enumeration enum Vektorin colIDs alkiot 416 * int i Laskurimuuttuja 417 * String thisHeader Käsiteltävä sarakeotsikko 418 ***********************************************************************************************/ 419 private Vector sortColumnIdentifiers(Vector colIDs) 420 { 421 Enumeration enum = colIDs.elements(); 422 int i = 1; 423 for (; enum.hasMoreElements(); ) 424 { 425 String thisHeader = (String)enum.nextElement(); 426 thisHeader = "Col"+i; 427 colIDs.setElementAt(thisHeader, i-1); 428 i++; 429 } 430 return colIDs; 431 } 432 /*********************************************************************************************** 433 * Metodi getTableData 434 * ================= 435 * Hakee taulukkodatan URL-osoitteesta 436 * 437 * Parametrit String sourceURL 438 * 439 * Paikalliset muuttujat 440 *---------------------- 441 * DataHandler thisHandler Palautettava DataHandler-objekti, joka kerää 442 * XML-parserin lukeman datan vektoriin 443 ***********************************************************************************************/ 444 private Vector getTableData(String sourceURL) 445 { 446 DataHandler thisHandler = new DataHandler(sourceURL); 447 return thisHandler.get(); 448 } 449 /*********************************************************************************************** 450 * Metodi toXML 451 * ================= 452 * Tekee datavektorista XML-stringin 453 * 454 * Parametrit Ei ole 455 * 456 * Paikalliset muuttujat 457 *---------------------- 458 * StringBuffer sb Tähän kerätään XML-merkkijono 459 * dataVector TableModelin datavektori 460 ***********************************************************************************************/ 461 private String toXML() 462 { 463 StringBuffer sb = new StringBuffer(); 464 Vector dataVector = getDataVector(); 465 if (dataVector.size() == 0) 466 { 467 return ""; 468 } 469 // encoding voisi olla muukin kuin windows-1252 470 // Pitäisi määritellä appletin parametreissa 471 sb.append("<?xml version='1.0' encoding='windows-1252' ?>\n"); 472 sb.append("<table>\n"); 473 for (int r=0; r < dataVector.size(); r++) 474 { 475 sb.append("<tr>\n"); 476 Vector row = (Vector)dataVector.get(r); 477 for (int i=0; i < row.size(); i++) 478 { 479 sb.append("<td>"+row.get(i)+"</td>\n"); 480 } 481 sb.append("</tr>\n"); 482 } 483 sb.append("</table>"); 484 return sb.toString(); 485 } 486 /*********************************************************************************************** 487 * Metodi post 488 * ================= 489 * HTTP-postaa XML-stringin serverille 490 * 491 * Parametrit String XMLString 492 * 493 * Paikalliset muuttujat 494 *---------------------- 495 * URL url URL johon postataan 496 * URLConnection con Connection-objekti, saadaan url.openConnetion:illa 497 * String msg Post-muuttuja, joka luetaan serverillä. Sisältää XML-dataa 498 * OutputStream os Outputstream, johon kirjoitetaan postattaessa 499 * OutputStreamWriter osw OutputStreamWriter, joka huolehtii varsinaisesta kirjoittamisesta 500 * InputStream is InputStream, jonka avulla luetaan serverin vastaus 501 * InputStreamReader isr InputStreamReader, joka lukee serverin vastauksen 502 * BufferedReader bsr Tämä on tätä JAVA-iota... 503 * String line Otetaan serveriltä tuleva data riveittäin tähän 504 ***********************************************************************************************/ 505 private void post(String XMLString) 506 { 507 try 508 { 509 // get the url as a string 510 // String surl = "http://localhost/labonet/XMLtable.hb"; 511 // URL url = new URL(surl); 512 URL url = new URL(m_sURL); 513 URLConnection con = url.openConnection(); 514 // System.out.println("Received a : " + con.getClass().getName()); 515 con.setDoInput(true); 516 con.setDoOutput(true); 517 con.setUseCaches(false); 518 519 String msg = "msg="+URLEncoder.encode(XMLString, "ISO-8859-1"); 520 con.setRequestProperty("CONTENT_LENGTH", "" + msg.length()); 521 OutputStream os = con.getOutputStream(); 522 OutputStreamWriter osw = new OutputStreamWriter(os); 523 osw.write(msg); 524 osw.flush(); 525 osw.close(); 526 527 InputStream is = con.getInputStream(); 528 // any response? 529 InputStreamReader isr = new InputStreamReader(is); 530 BufferedReader br = new BufferedReader(isr); 531 String line; 532 while (null != ((line = br.readLine()))) 533 { 534 // System.out.println("line: " + line); 535 } 536 } 537 catch (Throwable t) 538 { 539 t.printStackTrace(); 540 } 541 return; 542 } 543 /*********************************************************************************************** 544 * Metodi setURL 545 * ================= 546 * Asettaa jäsenmuuttujan m_sURL 547 * 548 * Parametrit String SourceURL 549 ***********************************************************************************************/ 550 public void setURL(String sourceURL) 551 { 552 m_sURL = sourceURL; 553 } 554 /*********************************************************************************************** 555 * Metodi writeToFile 556 * ================= 557 * Testiohjelman käyttämä metodi, joka kirjoittaa levytiedostoon 558 * 559 * Parametrit String XMLString 560 * 561 * Paikalliset muuttujat 562 *---------------------- 563 * FileWriter thisFileWriter Hoitaa kirjoittamisen 564 ***********************************************************************************************/ 565 private void writeToFile(String XMLString) 566 { 567 try 568 { 569 FileWriter thisFileWriter = new FileWriter(m_sURL); 570 thisFileWriter.write(XMLString); 571 thisFileWriter.close(); 572 } 573 catch (Throwable t) 574 { 575 t.printStackTrace(); 576 } 577 } 578 // Overrided toString 579 public String toString() 580 { 581 return toXML(); 582 } 583 }